<?php
    //RAuth Accounts Model
    
    class Ram extends Model 
    {        
        var $db_prefix;
        var $ci;
        var $last_error_code;
        
        
        function Ram()
        {
            parent::Model();
            $this->ci = &get_instance();
            $this->ci->config->load('rauth_config',TRUE);
            $this->ci->config->load('rauth_constants',TRUE);
            $this->db_prefix = $this->ci->config->item('db_prefix','rauth_config' );
            if(!class_exists('Rauth') )
                $this->ci->load->library('Rauth');
            // No errors at the moment
            $this->_set_error_code( ERR_NO_ERROR );            
        } 
        
        function _table_name( $tableName )
        {
            return $this->db_prefix.'_'.$tableName;
        }
        
        function _set_error_code( $code )
        {
            $this->last_error_code = $code;
        }
        /**
        * Returns the last error occured
        * 
        */
        function get_last_error() 
        {
            return $this->$last_error_code;
        }            
           
        /**
        * retrieves user_row from users table by username
        * 
        * @param string $username
        */        
        function find_user_by_username( $username )
        {
            $this->db->where('username',$username );
            log_message('debug', $this->db->_compile_select() );
            $result = $this->db->get( $this->_table_name('users') );
            log_message('debug', ' Result is :'.$result->num_rows());
            if( $result->num_rows() == 1 )
                return $result->row();
            log_message('debug', ' returnin null');
            return null;
        }
        /**
        * retrieves user_row from users table by email
        * 
        * @param string $email
        */
        function find_user_by_email( $email )
        {
            $this->db->where('email',$email );
            $result = $this->db->get( $this->_table_name('users') );
            if( $result->num_rows()==1 )
                return $result->row();
            return null;
        }
        /**
        * retrieves user_row from users table by primary key { id }
        * 
        * @param integer $id
        */
        function find_user_by_id( $id )
        {
            $this->db->where('id',$id );
            $result = $this->db->get( $this->_table_name('users') );
            if( $result->num_rows()>0 )
                return $result->row();
            return null;
        }
        
        /**
        * Creates a user and inserts into database.
        * Returns user_id on success or -1 on failure
        *         
        * @param string $email
        * @param string $password
        */
        function create_user( $email, $password,$username=null )
        {
            $salt='';
            if( $this->ci->config->item('use_password_salt','rauth_config') == TRUE )            
                $salt = $this->ci->rauth->_generate_salt();
            
            $user_password = $this->ci->rauth->do_hash( $password, $salt );    
            log_message('debug','User password is :'.$user_password );
            $confirm_hash = md5( microtime() );
            $data = array(  'email'=> $email,
                            'username'=>$username,
                            'password' => $user_password,
                            'password_salt'=>$salt,
                            'confirm_hash'=>$confirm_hash
                          );
            if( $this->db->insert( $this->_table_name('users') , $data ) )
            {
                
                $id = $this->db->insert_id();
                log_message('debug','RAM created new user ( '.$id.' )');            
                if( $this->ci->config->item('send_mail_after_create','rauth_config') == TRUE )
                {
                    log_message('debug','RAM sending new user a message');            
                    $this->ci->rauth->send_activation_mail( $id, $confirm_hash );                    
                }   
                else
                    log_message('debug','Configuation does not allow RAM to send a message!');                             
                return $id;
            }
            return -1;
        }
        /**
        * Bans the user
        * 
        * @param integer $user_id
        */
        function ban_user( $user_id )
        {
            $users_table = $this->_table_name( 'users' ); 
            return $this->db->query("update $users_table set banned=1 where id=$user_id");
        }
        /**
        * unbans the user
        * 
        * @param integer $user_id
        */
        function unban_user( $user_id )
        {
            $users_table = $this->_table_name( 'users' ); 
            return $this->db->query("update $users_table set banned=0 where id=$user_id");
        }        
        
        /**
        * Activates the user account
        * 
        * @param integer $user_id
        * @param string  $confirm_hash
        */
        function activate_user_account( $user_id ,$confirm_hash )
        {
            $user_row = $this->find_user_by_id( $user_id );
            if( !isset($user_row) )
                return false;
            if( $user_row->confirm_hash == $confirm_hash )
            {
                $this->db->where('id',$user_row->id );
                return $this->db->update( $this->_table_name('users'),array('confirm_hash'=>'null','confirmed'=>1));                
            }
            return false;
        }
        /**
        * updates the last_login field and completes the authentication process
        * 
        * @param integer $user_id
        */
        function complete_authentication( $user_id )
        {
            $users_table = $this->_table_name( 'users' );
            $this->db->query("update $users_table set last_login=NOW() where id= $user_id");
        }
        /**
        * Changes user password
        * 
        * @param integer $user_id
        * @param string $old_pass
        * @param string $new_pass
        */
        function change_password( $user_id,$old_pass, $new_pass )
        {
            $user_row = $this->find_user_by_id( $user_id );
            if( !isset($user_row) )
                return false;
            $old_pass_hash = $this->rauth->do_hash( $old_pass, $user_row->password_salt );
            if( $user_row->password == $old_pass_hash )
            {
                $new_pass_hash = $this->rauth->do_hash( $new_pass, $user_row->password_salt );    
                $user_table = $this->_table_name('users');
                $this->db->query("update $user_table set password='$new_pass_hash' where id={$user_row->id}");
                return true;
            }    
            return false;
        }
        /**
        * * 
        * Initiates a password reset process
        *         
        * @param integer $user_id
        * @return string password hash
        */
        function create_password_reset_hash( $user_id )
        {
            $user_table = $this->_table_name('users');
            $hash = md5(microtime());
            $this->db->query("update $user_table set password_reset_end_time=( now() + INTERVAL '2' DAY  ),password_reset_hash='$hash' where id= $user_id");
            return $hash;
        }        
        /**
        * Generates a new password for the user 
        * 
        * @param integer $user_id
        * @return string password;
        */
        function reset_password( $user_id )
        {
            $user_row = $this->find_user_by_id( $user_id );
            $new_pass = substr( md5(uniqid(mt_rand(), true)),1,7 );
            $new_pass_hash = $this->ci->rauth->do_hash( $new_pass, $user_row->password_salt );    
            $user_table = $this->_table_name('users');
            $this->db->query("update $user_table set password_reset_hash=null,password='$new_pass_hash' where id = $user_id" );
            return $new_pass;
        }
        
        /**
        * GROUP FUNCTIONS
        */
        
    
        /**
        * creates a group
        *         
        * @param string $group_name
        * @param string $group_label
        */
        function create_group( $group_name, $group_label )
        {
            if( !isset($group_name))
                return false;
            $table_name = $this->_table_name('groups');
            if( $this->db->insert( $table_name, array('name'=>$group_name,'label'=>$group_label)) )
                return $this->db->insert_id();
            else    
                return -1;
        }
        /**
        * returns group table row
        * 
        * @param string $group_name
        */
        function find_group_by_name( $group_name )
        {   
            $table_name = $this->_table_name('groups');              
            $result = $this->db->query("select * from $table_name where name='$group_name'");
            if( $result->num_rows() == 1 )
                return $result->row();
            return null;                
        }
        /**
        * return groups tbale row
        * 
        * @param integer $group_id
        */
        function find_group_by_id( $group_id )
        {   
            $table_name = $this->_table_name('groups');              
            $result = $this->db->query("select * from $table_name where id=$group_id");
            if( $result->num_rows() == 1 )
                return $result->row();
            return null;
        }  
        /**
        * Returns the group id
        * 
        * @param string $group_name
        */
        function find_group_id( $group_name )   
        {
            $table_name = $this->_table_name('groups');              
            $result = $this->db->query("select id from $table_name where name='$group_name'");
            if( $result->num_rows() == 1 )
                return $result->row()->id;
            return null;                
        }   
        /**
        * updates group data
        * 
        * @param integer $id
        * @param string $group_name
        * @param string $group_label
        */
        function update_group_by_id( $id, $group_name, $group_label )
        {
            if( !isset($group_name) || !isset($id) )
                return false;            
            $table_name = $this->_table_name('groups');    
            
            $this->db->where('id',$id);            
            return $this->db->update($table_name,array('name'=>$group_name,'label'=>$group_label));
        }
        /**
        * Changes group name
        * 
        * @param string $old_group_name
        * @param string  $new_group_name
        */
        function change_group_name( $old_group_name, $new_group_name)
        {        
            $group_row = $this->find_group_by_name( $old_group_name );
            if( !isset($group_row))
                return false;
            return $this->update_group_by_id( $group_row->id, $new_group_name, $group_row->label);
        }
        /**
        * Changes group label
        *  
        * @param string $group_name
        * @param string $new_label
        */
        function change_group_label( $group_name, $new_label)
        {        
            $group_row = $this->find_group_by_name( $group_name );
            if( !isset($group_row))
                return false;
            return $this->update_group_by_id( $group_row->id, $group_name, $new_label);
        }
        /**
        * deletes group. developer should check group_member_count before removing :)
        * 
        * @param string $group_name
        */
        function remove_group( $group_name )
        {
            $group_row = $this->find_group_by_name( $group_name );
            if( !isset($group_row))
                return false;
            $group_users_table = $this->_table_name('group_users');
            $this->db->where('id',$group_row->id);
            return $this->db->delete( $this->_table_name('groups'));            
        }
        /**
        * Return the number of members who belong to our group
        * 
        * @param integer $gid
        */
        function group_member_count( $gid )
        {
            $group_users = $this->db->query("Select count(id) user_count from $group_users_table where gid = {$group_row->id}");
            $r = $group_users->row();
            return $r->user_count;            
        }
        /**
        * returns true if group has any members
        * 
        * @param integer $gid
        */
        function group_has_members( $gid )
        {
            return $this->group_member_count( $gid ) > 0 ;
        }
        /**
        * Test whether a user is a member of group or not
        * 
        * @param integer $uid
        * @param integer $gid
        */
        function user_is_a_member_of( $uid, $gid )
        {
            $table_name = $this->_table_name('group_users');
            $result = $this->db->query("Select id from $table_name where uid=$uid and gid=$gid");
            return $result->num_rows() == 1;
            
        }
        /**
        * Makes user a member of group
        * 
        * @param integer $uid
        * @param integer $gid
        */
        function add_user_to_group( $uid, $gid )
        {            
            $table_name = $this->_table_name('group_users');
            return $this->db->insert( $table_name, array('uid'=>$uid,'gid'=>$gid) ); 
        }
        /**
        * removes user from group
        * 
        * @param integer $uid
        * @param integer $gid
        */
        function remove_user_from_group( $uid, $gid )
        {
            $this->db->where('uid',$uid);
            $this->db->where('gid',$gid);
            return $this->db->delete( $this->_table_name('group_users'));
        }
        
        
    }
?>
